package com.bf.electroplating.util;

import com.bf.electroplating.pojo.entity.EnterpriseOutfallMonitoringData;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * HJ212协议监测数据解析工具类
 * 解析企业上报的监测数据报文并填充到EnterpriseOutfallMonitoringData实体中
 * 
 * @author system
 * @since 2025-10-09
 */
@Slf4j
public class HJ212MonitoringDataParser {

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

    /**
     * 解析监测数据并填充到实体对象
     * 
     * @param cpData CP段数据内容（&&之间的数据）
     * @param monitoringData 要填充的实体对象
     * @return 解析是否成功
     */
    public static boolean parseMonitoringData(String cpData, EnterpriseOutfallMonitoringData monitoringData) {
        try {
            if (cpData == null || cpData.isEmpty()) {
                log.warn("CP数据为空");
                return false;
            }

            // 解析数据时间
            if (cpData.startsWith("DataTime=")) {
                int endIndex = cpData.indexOf(";");
                if (endIndex > 0) {
                    String dataTimeStr = cpData.substring(9, endIndex);
                    LocalDateTime dataTime = LocalDateTime.parse(dataTimeStr, DATE_TIME_FORMATTER);
                    monitoringData.setDataTime(dataTime);
                    
                    // 去掉DataTime部分
                    cpData = cpData.substring(endIndex + 1);
                }
            }

            // 解析各个监测因子数据
            String[] factorDataArray = cpData.split(";");
            for (String factorData : factorDataArray) {
                if (factorData.trim().isEmpty()) {
                    continue;
                }
                parseFactorData(factorData, monitoringData);
            }

            return true;
        } catch (Exception e) {
            log.error("解析监测数据失败：{}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 解析单个因子的数据
     * 
     * @param factorData 因子数据字符串（如：w21001-Min=11.026,w21001-Max=11.031,w21001-Avg=11.029,w21001-Cou=0.000,w21001-Flag=N）
     * @param monitoringData 要填充的实体对象
     */
    private static void parseFactorData(String factorData, EnterpriseOutfallMonitoringData monitoringData) {
        try {
            // 提取因子编码（如：w21001）
            String factorCode = extractFactorCode(factorData);
            if (factorCode == null) {
                log.warn("无法提取因子编码：{}", factorData);
                return;
            }

            // 获取字段前缀（如：cod）
            String fieldPrefix = HJ212FactorCodeMapping.getFieldPrefix(factorCode);
            if (fieldPrefix == null) {
                log.debug("未配置的因子编码：{}", factorCode);
                return;
            }

            // 解析Min、Max、Avg、Cou、Flag值
            Map<String, String> values = parseFactorValues(factorData, factorCode);

            // 使用反射设置字段值
            setFieldValues(monitoringData, fieldPrefix, values);

        } catch (Exception e) {
            log.error("解析因子数据失败：{}, 错误：{}", factorData, e.getMessage());
        }
    }

    /**
     * 提取因子编码
     * 
     * @param factorData 因子数据字符串
     * @return 因子编码
     */
    private static String extractFactorCode(String factorData) {
        if (factorData.contains("-")) {
            int dashIndex = factorData.indexOf("-");
            return factorData.substring(0, dashIndex);
        }
        return null;
    }

    /**
     * 解析因子的各项值（Min、Max、Avg、Cou、Flag）
     * 
     * @param factorData 因子数据字符串
     * @param factorCode 因子编码
     * @return 各项值的Map
     */
    private static Map<String, String> parseFactorValues(String factorData, String factorCode) {
        Map<String, String> values = new HashMap<>();
        
        String[] parts = factorData.split(",");
        for (String part : parts) {
            if (part.contains("=")) {
                String[] kv = part.split("=", 2);
                String key = kv[0].trim();
                String value = kv[1].trim();

                if (key.startsWith(factorCode)) {
                    if (key.endsWith("-Min")) {
                        values.put("min", value);
                    } else if (key.endsWith("-Max")) {
                        values.put("max", value);
                    } else if (key.endsWith("-Avg")) {
                        values.put("avg", value);
                    } else if (key.endsWith("-Cou")) {
                        values.put("cou", value);
                    } else if (key.endsWith("-Flag")) {
                        values.put("flag", value);
                    }
                }
            }
        }
        
        return values;
    }

    /**
     * 使用反射设置字段值
     * 
     * @param monitoringData 实体对象
     * @param fieldPrefix 字段前缀
     * @param values 各项值的Map
     */
    private static void setFieldValues(EnterpriseOutfallMonitoringData monitoringData, 
                                       String fieldPrefix, Map<String, String> values) {
        try {
            Class<?> clazz = EnterpriseOutfallMonitoringData.class;

            // 设置Min值
            if (values.containsKey("min")) {
                String methodName = "set" + capitalize(fieldPrefix) + "Min";
                Method method = clazz.getMethod(methodName, BigDecimal.class);
                method.invoke(monitoringData, new BigDecimal(values.get("min")));
            }

            // 设置Max值
            if (values.containsKey("max")) {
                String methodName = "set" + capitalize(fieldPrefix) + "Max";
                Method method = clazz.getMethod(methodName, BigDecimal.class);
                method.invoke(monitoringData, new BigDecimal(values.get("max")));
            }

            // 设置Avg值
            if (values.containsKey("avg")) {
                String methodName = "set" + capitalize(fieldPrefix) + "Avg";
                Method method = clazz.getMethod(methodName, BigDecimal.class);
                method.invoke(monitoringData, new BigDecimal(values.get("avg")));
            }

            // 设置Cou值
            if (values.containsKey("cou")) {
                String methodName = "set" + capitalize(fieldPrefix) + "Cou";
                Method method = clazz.getMethod(methodName, BigDecimal.class);
                method.invoke(monitoringData, new BigDecimal(values.get("cou")));
            }

            // 设置Flag值
            if (values.containsKey("flag")) {
                String methodName = "set" + capitalize(fieldPrefix) + "Flag";
                Method method = clazz.getMethod(methodName, String.class);
                method.invoke(monitoringData, values.get("flag"));
            }

        } catch (Exception e) {
            log.error("设置字段值失败：{}, 错误：{}", fieldPrefix, e.getMessage());
        }
    }

    /**
     * 首字母大写
     * 
     * @param str 字符串
     * @return 首字母大写的字符串
     */
    private static String capitalize(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    /**
     * 解析完整的HJ212报文
     * 
     * @param message 完整报文
     * @return 解析后的监测数据对象
     */
    public static EnterpriseOutfallMonitoringData parseFullMessage(String message) {
        try {
            EnterpriseOutfallMonitoringData monitoringData = new EnterpriseOutfallMonitoringData();
            monitoringData.setCreateTime(LocalDateTime.now());
            monitoringData.setUpdateTime(LocalDateTime.now());
            monitoringData.setIsValid(true);
            monitoringData.setDataSource("AUTO");

            // 提取CP段数据
            int cpStart = message.indexOf("&&") + 2;
            int cpEnd = message.lastIndexOf("&&");
            
            if (cpStart > 1 && cpEnd > cpStart) {
                String cpData = message.substring(cpStart, cpEnd);
                parseMonitoringData(cpData, monitoringData);
            }

            // 提取MN（设备编号）
            String mn = extractValue(message, "MN=");
            if (mn != null) {
                monitoringData.setOutfallCode(mn);
            }

            return monitoringData;
        } catch (Exception e) {
            log.error("解析完整报文失败：{}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 从报文中提取指定字段的值
     * 
     * @param message 报文
     * @param key 字段名（如：MN=）
     * @return 字段值
     */
    private static String extractValue(String message, String key) {
        int startIndex = message.indexOf(key);
        if (startIndex < 0) {
            return null;
        }
        startIndex += key.length();
        
        int endIndex = message.indexOf(";", startIndex);
        if (endIndex < 0) {
            endIndex = message.length();
        }
        
        return message.substring(startIndex, endIndex);
    }
}

